﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmoLiteApi.Sql;
using System.Data.SqlClient;
using SmoLiteApi.Helper;

namespace SmoLiteApi
{
    /// <summary/>
    public class View
    {
        private Database _database;
        private string _name;
        private string _schemaName;
        private string _text;
        private IndexCollection _indexCollection;
        private FullTextIndex _fullTextIndex;

        /// <summary/>
        public View(
            Database database,
            string name,
            string schemaName,
            string text)
        {
            this._database = database;
            this._name = name;
            this._schemaName = schemaName;
            this._text = text;
            this._indexCollection = new IndexCollection();
        }

        /// <summary/>
        public Database Parent
        {
            get { return this._database; }
        }

        /// <summary/>
        public string Name
        {
            get { return this._name; }
        }

        /// <summary/>
        public string Text
        {
            get { return this._text; }
        }

        /// <summary/>
        public string Schema
        {
            get { return this._schemaName; }
        }

        /// <summary/>
        public IndexCollection Indexes
        {
            get { return this._indexCollection; }
        }

        /// <summary/>
        public FullTextIndex FullTextIndex
        {
            get { return this._fullTextIndex; }
            set { this._fullTextIndex = value; }
        }

        /// <summary/>
        public void Create()
        {
            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, this._text))
            {
                // run the command
                sqlCommandHelper.ExecuteNonQuery();
            }

            foreach (Index index in this._indexCollection)
            {
                CommonIndexCreateSql indexCreateSql = new CommonIndexCreateSql();

                // set attributes
                indexCreateSql.AddObject(new { View = this._name, Schema = this._schemaName });
                indexCreateSql.AddObject(index);

                using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, indexCreateSql.Render()))
                {
                    // run the command
                    sqlCommandHelper.ExecuteNonQuery();
                }
            }

            // was it set
            if (this._fullTextIndex != null)
            {
                ViewFullTextIndexCreateSql fullTextIndexCreateSql = new ViewFullTextIndexCreateSql();

                // set attributes
                fullTextIndexCreateSql.AddObject(new { View = this._name, Schema = this._schemaName });
                fullTextIndexCreateSql.AddObject(this._fullTextIndex);

                using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, fullTextIndexCreateSql.Render()))
                {
                    // run the command
                    sqlCommandHelper.ExecuteNonQuery();
                }
            }
        }

        /// <summary/>
        public void Drop()
        {
            ViewDropSql storedProcedureDropSql = new ViewDropSql();

            // set attributes
            storedProcedureDropSql.AddObject(new { Name = this._name, Schema = this._schemaName});

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, storedProcedureDropSql.Render()))
            {
                // run the command
                sqlCommandHelper.ExecuteNonQuery();
            }
        }

        /// <summary/>
        public void Grant(ObjectPermissionSet objectPermissionSet, string granteeName, bool grantGrant)
        {
            ObjectGrantSql objectGrantSql = new ObjectGrantSql();

            // set attributes
            objectGrantSql.AddObject(new 
            { 
                Name = this._name, 
                Schema = this._schemaName, 
                Grantee = granteeName, 
                GrantGrant = grantGrant, 
                ObjectPermissionSet = objectPermissionSet
            });

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, objectGrantSql.Render()))
            {
                // run the command
                sqlCommandHelper.ExecuteNonQuery();
            }
        }

        /// <summary/>
        public IEnumerable<ObjectPermissionInfo> EnumObjectPermissions(ObjectPermissionSet objectPermissionSet)
        {
            List<ObjectPermissionInfo> objectPermissionInfos = new List<ObjectPermissionInfo>();

            ObjectPrincipalSelectSql objectPrincipalSelectSql = new ObjectPrincipalSelectSql();

            // set attributes
            objectPrincipalSelectSql.AddObject(new
            {
                Name = this._name,
                Schema = this._schemaName,
                ObjectPermissionSet = objectPermissionSet
            });

            using (SqlCommandHelper sqlCommandHelper = SqlCommandHelper.FetchSqlCommand(this._database.SqlConnection, objectPrincipalSelectSql.Render()))
            {
                using (SqlDataReader sqlDataReader = sqlCommandHelper.ExecuteReader())
                {
                    while (sqlDataReader.Read())
                    {
                        ObjectPermissionInfo objectPermissionInfo = new ObjectPermissionInfo();
                        
                        // record the name
                        objectPermissionInfo.Grantee = sqlDataReader.GetString(sqlDataReader.GetOrdinal(Constant.PARAMETER_NAME));

                        // add to the collection
                        objectPermissionInfos.Add(objectPermissionInfo);
                    }
                }
            }

            // return
            return objectPermissionInfos;
        }
    }
}
